/**
 * @file form reducer
 * @author liaoxuezhi@baidu.com
 */
/* eslint fecs-indent: [0, "space", 2, 2] */

import {
  REQ_FETCH_CRUD,
  REC_FETCH_CRUD,

  REQ_QUICK_SAVE,
  REC_QUICK_SAVE,

  REQ_SAVE_ORDER,
  REC_SAVE_ORDER,

  // 其他 Action
  REQ_ACTION,
  REC_ACTION,

  // 其他批量操作
  REQ_BULK_ACTION,
  REC_BULK_ACTION,

  CLEAR_CRUD

} from './action-types';
import {handleActions, createAction} from 'redux-actions';
import * as update from 'react-addons-update';
import * as assign from 'object-assign';
import {findIndexById} from '../../util/helper';
import {createRequestReducer, createReceiveReducer, compose} from '../renderer';

function rawObject(object) {
  const data = {};
  Object.keys(object).forEach(key => key[0] !== '$' && (data[key] = object[key]));
  return data;
}

function buildPagerInfo(response, params, state) {
  const perPage =  parseInt(params.perPage, 10) || state.perPage || 10;
  const total = parseInt(response.count, 10) || 0;

  return {
    currentPage: parseInt(params.page, 10) || 1,
    lastPage: Math.ceil(total / perPage),
    perPage,
    total,
    hasMore: !!response.hasMore
  };
}

export default handleActions({

  // 获取数据
  [REQ_FETCH_CRUD]: createRequestReducer(),
  [REC_FETCH_CRUD]: compose((state, action) => action.error ? state : update(state, {
    pager: {
      $merge: action.payload.data
      && (action.payload.data.hasOwnProperty('count') || action.payload.data.hasOwnProperty('hasMore'))
        ? buildPagerInfo(action.payload.data, state.ctx, state.pager)
        : {}
    },
    data: {
      $set: Array.isArray(action.payload.data) ? {rows: action.payload.data} : action.payload.data
    }
  }), createReceiveReducer()),

  // 快速修改批量保存
  [REQ_QUICK_SAVE]: createRequestReducer('saving', 'quickSave'),
  [REC_QUICK_SAVE]: compose((state, action) => action.error ? state : update(state, {
    data: {
      $apply: data => {
        const rows = data.rows.concat();
        let updated = action.payload.data && action.payload.data.length
          ? action.payload.data : state.quickSave.ctx.rows;

        updated && updated.forEach(item => {
          if (item.hasOwnProperty('$index')) {
            rows[item.$index] = assign({}, rows[item.$index], rawObject(item));
          } else if (item.id) {
            const idx = findIndexById(rows, item.id);
            if (~idx) {
              rows[idx] = assign({}, rows[idx], rawObject(item));
            }
          }
        });

        return assign({}, data, {
          rows
        });
      }
    }
  }), createReceiveReducer('saving', 'quickSave')),

  // 保存顺序
  [REQ_SAVE_ORDER]: createRequestReducer('saving', 'saveOrder'),
  [REC_SAVE_ORDER]: compose((state, action) => update(state, {
    invalid: {
      $set: true // 标记失效, 需要重新刷新
    }
  }), createReceiveReducer('saving', 'saveOrder')),


  // 单条操作
  [REQ_ACTION]: createRequestReducer('saving', 'action'),
  [REC_ACTION]: compose((state, action) => update(state, {
    invalid: {
      $set: true // 标记失效, 需要重新刷新
    },
    action: {
      data: {
        $set: action.error ? state.action.data : action.payload.data
      }
    }
  }), createReceiveReducer('saving', 'action')),


  // 批量操作
  [REQ_BULK_ACTION]: createRequestReducer('saving', 'bulkAction'),
  [REC_BULK_ACTION]: compose((state, action) => update(state, {
    invalid: {
      $set: true // 标记失效, 需要重新刷新
    }
  }), createReceiveReducer('saving', 'bulkAction')),

  [CLEAR_CRUD]: state => update(state, {
    data: {
      $set: {
        rows: []
      }
    },
    pager: {
      $set: {
        currentPage: 1,
        perPage1: 10,
        lastPage: 1,
        total: 0
      }
    }
  })

// initState
}, {
  data: {
    rows: []
  },
  pager: {
    currentPage: 1,
    perPage1: 10,
    lastPage: 1,
    total: 0
  },
  fetching: false,
  saving: false,
  invalid: false,
  error: null,
  ctx: null,

  quickSave: {
    ctx: null,
    message: null,
    saving: false,
    invalid: false,
    error: null
  },

  saveOrder: {
    ctx: null,
    message: null,
    saving: false,
    invalid: false,
    error: null
  },

  action: {
    ctx: null,
    message: null,
    saving: false,
    invalid: false,
    error: null
  },

  bulkAction: {
    ctx: null,
    message: null,
    saving: false,
    invalid: false,
    error: null
  }
});